package com.anxin.act.task.service;

import com.anxin.act.task.cmd.JumpTaskCmd;
import com.anxin.act.task.cmd.UpdateHiTaskReasonCmd;
import com.anxin.act.utils.ActTaskUtils;
import com.anxin.act.utils.ActUtils;
import com.anxin.common.utils.StringUtils;
import com.anxin.common.utils.sys.UserUtils;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.RuntimeServiceImpl;
import org.activiti.engine.impl.interceptor.CommandExecutor;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author: liuxiangyu
 * @date: 2020/4/26 19:24
 */
@Service
public class JumpTaskService {


    @Autowired
    private TaskService taskService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private ActSendCcService actSendCcService;

    /**
     * 跳过需要AA跳或者ABA跳的节点
     * @param procInsId 流程实例ID
     * @param sourceTaskId  跳过前提交的任务ID
     */
    public void jumpTask(String procInsId,String sourceTaskId){
        List<Task> currentTaskList = ActTaskUtils.getCurrentTaskList(procInsId);

        for (Task task : currentTaskList) {

            // 查询 activityImpl 对象
            ActivityImpl activityImpl = ActUtils.getActivityImpl(task);

            // 是否可以AA跳
            boolean skipTask = this.getActivityProperty(activityImpl,"skiptask");

            //是否ABA跳
            boolean skipTaskAba = this.getActivityProperty(activityImpl,"skiptaskaba");

            //审批人为空是否跳过
            boolean approvalNullSkipTask = this.getActivityProperty(activityImpl,"approvalnullskiptask");

            // 当前这个任务所有审批人，包含未签收的
            List<String> assigneeList = ActUtils.getAssigneeByTask(task);

            // 跳过节点时携带的变量
            Map<String,Object> completeVars = new HashMap<>();
            completeVars.put("completeType","jumpTask");


            //没有找到审批人
            if (assigneeList.size() == 0){
                // 审批人为空跳过
                if (approvalNullSkipTask){

                    this.claimAndJump(task,"-1","审批人为空,自动跳过",completeVars);
                    // 默认发送抄送信息
                    actSendCcService.sendCc(task.getId());
                    return;

                }else {//不跳过
                    ActTaskUtils.claimTask(task.getId(), "-1");
                    taskService.setAssignee(task.getId(), "-1");

                }

            }else  if (assigneeList.size() == 1){// 只找到一个审批人

                String userName = assigneeList.get(0);
                // 签收任务
                ActTaskUtils.claimTask(task.getId(),userName);
                // 如果审批人是当前用户，则判断是否需要AA调，或者ABA跳
                if ( UserUtils.currentByUserName(userName)){
                    // AA跳
                    if (skipTask){
                        this.complete(task,"与上节点审批人相同,自动跳过",completeVars);
                        // 默认发送抄送信息
                        actSendCcService.sendCc(task.getId());
                        return;

                    }
                }else if (skipTaskAba){
                    // ABA跳
                    this.skipTaskAbaJump(task,userName,completeVars);
                    // 默认发送抄送信息
                    actSendCcService.sendCc(task.getId());
                }


            }

            //this.jumpTask(assigneeList,skipTask,skipTaskAba,approvalNullSkipTask);


        }

    }

    /**
     * ABA跳
     * @param task
     * @param userName
     * @param completeVars
     */
    public void skipTaskAbaJump(Task task,String userName,Map<String,Object> completeVars){

        List<HistoricTaskInstance> taskList = historyService.createHistoricTaskInstanceQuery().processInstanceId(task.getProcessInstanceId()).includeTaskLocalVariables().orderByHistoricTaskInstanceEndTime().desc().list();

        for (HistoricTaskInstance historicTaskInstance : taskList) {
            List<Comment> taskComments = taskService.getTaskComments(historicTaskInstance.getId());
            for (Comment taskComment : taskComments) {
                if(StringUtils.isNotBlank(taskComment.getFullMessage()) && (taskComment.getFullMessage().indexOf("审批结果:不同意") == 0 || taskComment.getFullMessage().indexOf("审批结果:驳回") == 0)){
                    return;
                }
            }

            if (userName.equals(historicTaskInstance.getAssignee())){
                Map<String, Object> taskLocalVariables = historicTaskInstance.getTaskLocalVariables();
                String approved = taskLocalVariables.get("approved")!=null?taskLocalVariables.get("approved").toString():null;
                if (StringUtils.isNotBlankAndEquals(approved,"同意") || "jump".equals(historicTaskInstance.getDeleteReason())){
                    this.complete(task,StringUtils.join("与",historicTaskInstance.getName(),"节点审批人相同,自动跳过"),completeVars);
                    return;
                }
            }
        }

    }

    /**
     * 签收并跳过任务
     * @param task 待办对象
     * @param assignee 审批人
     * @param comment 跳过时的审批意见
     * @param completeVars 跳过时携带的变量
     */
    public void claimAndJump(Task task,String assignee,String comment,Map<String,Object> completeVars){
        ActUtils.setAssignee(task,assignee);
        // 审批为为空自动跳过
        this.complete(task,comment,completeVars);
    }

    /**
     * 提交任务
     * @param task
     * @param comment
     */
    private void complete(Task task,String comment){
        this.complete(task,comment,new HashMap<>());
    }


    /**
     * 提交任务
     * @param task
     * @param comment
     * @param vars
     */
    private void complete(Task task,String comment, Map<String, Object> vars){
        // 默认的审批意见
        vars.put("approved","同意");

        taskService.addComment(task.getId(),task.getProcessInstanceId(), comment);
        taskService.complete(task.getId(),vars);
        CommandExecutor commandExecutor = ((RuntimeServiceImpl) runtimeService).getCommandExecutor();
        commandExecutor.execute(new UpdateHiTaskReasonCmd(task.getId(),"jump"));
        this.jumpTask(task.getProcessInstanceId(),task.getId());
    }

    /**
     * 获取流程属性
     * @param activityImpl
     * @param key
     * @return
     */
    private boolean getActivityProperty(ActivityImpl activityImpl,String key){
        if ("true".equals(activityImpl.getProperty(key))) {
            return true;
        }
        return false;
    }

    /**
     * 跳转（包括回退和向前）至指定活动节点
     * @param procInsId 流程实例ID
     * @param currentTaskId 当前任务ID
     * @param targetTaskDefinitionKey 目前节点的taskKey
     * @param variables 流程变量
     */
    public void jumpTask(String procInsId, String currentTaskId, String targetTaskDefinitionKey, Map<String, Object> variables) {
        TaskEntity task = (TaskEntity)taskService.createTaskQuery().taskId(currentTaskId).singleResult();
        jumpTask(task, targetTaskDefinitionKey, variables);
    }

    /**
     * 跳转（包括回退和向前）至指定活动节点
     * @param currentTaskEntity 当前任务节点
     * @param targetTaskDefinitionKey 目标任务节点（在模型定义里面的节点名称）
     * @throws Exception
     */
    public void jumpTask(TaskEntity currentTaskEntity, String targetTaskDefinitionKey, Map<String, Object> variables) {
        ActivityImpl activity = ActUtils.getActivityImpl(currentTaskEntity.getProcessDefinitionId(),targetTaskDefinitionKey);
        jumpTask(currentTaskEntity, activity, variables);
    }

    /**
     * 跳转（包括回退和向前）至指定活动节点
     * @param currentTaskEntity 当前任务节点
     * @param targetActivity 目标任务节点（在模型定义里面的节点名称）
     * @throws Exception
     */
    private void jumpTask(TaskEntity currentTaskEntity, ActivityImpl targetActivity, Map<String, Object> variables) {
        CommandExecutor commandExecutor = ((RuntimeServiceImpl) runtimeService).getCommandExecutor();
        commandExecutor.execute(new JumpTaskCmd(currentTaskEntity, targetActivity, variables));
    }

}
